/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.moderatorplugin;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.pearreview.ui.*;
import com.pearreview.ui.list.URIListCellRenderer;
import com.pearreview.application.Messages;
import com.pearreview.util.DoubleClickMouseAdapter;
import com.pearreview.util.review.Product;

public class InformationPanel extends PearPanel implements ModeratorPanel {

	private static final long serialVersionUID = 1054358500704598081L;
	
	private JLabel reviewNameLabel;
	private CompletableJTextField reviewName;
	private JLabel ReviewDescriptionLabel;
	private JScrollPane scrollPaneReviewDescription;
	private FadingTextArea reviewDescription;
	private JLabel reviewCommentsLabel;
	private JScrollPane scrollPaneReviewComments;
	private FadingTextArea reviewComments;
	private JSeparator separatorReviewProduct;
	private JLabel productNameLabel;
	private CompletableJTextField productName;
	private JLabel productVersionLabel;
	private CompletableJTextField productVersion;
	private JLabel productReferenceLabel;
	private FormLabel radioBtnRefAsText;
	private JScrollPane scrollPaneProductReference;
	private FadingTextArea productReferenceText;
	private JSeparator separatorReferenceTextFile;
	private FormLabel radioBtnRefAsFile;
	private JScrollPane scrollPaneReferenceFile;
	private JList productReferenceList;
	private DefaultListModel productReferenceModel;
	private JButton addReferenceBtn;
	private JButton deleteReferenceBtn;
	private File lastDir = null;
   
	private Product product;
	private BottomButtonPanel bottom;
	
	private Action deleteFileReferenceAction = new DeleteFileReferenceAction();
	
	public InformationPanel() {
			initComponents();
	}
   
	@Override
	public boolean isValidForm() {
		return true;
	}
	
	public void setReviewName(String reviewName) {
		this.reviewName.setText(reviewName);
	}
	
	public String getReviewName() {
		return this.reviewName.getText();
	}
	
	public void setReviewDescription(String reviewDescription) {
		this.reviewDescription.setText(reviewDescription);
	}
	
	public String getReviewDescription() {
		return this.reviewDescription.getText();
	}
	
	public void setReviewComments(String reviewComments) {
		this.reviewComments.setText(reviewComments);
	}
	
	public String getReviewComments() {
		return this.reviewComments.getText();
	}
	
	public void setProduct(Product product) {
		this.product = product;
		   
		this.productName.setText(product.getName());
		this.productVersion.setText(product.getVersion());
	   
		List<String> references = product.getReference();
		if (references != null)  {
			   
			Pattern pattern = Pattern.compile ("file:/.+");
			String oneText = "";
			for (String reference: references) {
   
				Matcher matcher = pattern.matcher (reference);
			   
				if (matcher.matches()) {
					//string is reference to file
					try {
						productReferenceModel.addElement(new URI(reference));
					} catch (URISyntaxException e) {
						 e.printStackTrace();
						 oneText += System.getProperty("line.separator")+
						 		System.getProperty("line.separator")+
						 		reference;
					}
				} else {
					//string is textual description
					if (oneText.equals("")) {
						oneText += reference;
					} else {
						oneText += System.getProperty("line.separator")
								+ System.getProperty("line.separator") +
									reference;
					}
				}
			}
			this.productReferenceText.setText(oneText);
		}
	}
	   
	/**
	 *
	 * @return
	 */
	public Product getProduct() {
		if(product == null)
			product = new Product();
	   
		product.setName(this.productName.getText());
		product.setVersion(this.productVersion.getText());
		   
		List<String> references = new ArrayList<String>();
		references.add(this.productReferenceText.getText());
		for (int i=0; i < this.productReferenceModel.size(); i++) {
			URI uri = (URI)productReferenceModel.get(i);
			references.add(uri.toString());
		}
		product.setReference(references);
	   
		return product;
	}

	private void initComponents() {
		setFont(new Font("Tahoma", Font.PLAIN, 12));
		
		reviewNameLabel = new JLabel();
		reviewName = new CompletableJTextField();
		ReviewDescriptionLabel = new JLabel();
		scrollPaneReviewDescription = new JScrollPane();
		reviewDescription = new FadingTextArea();
		reviewCommentsLabel = new JLabel();
		scrollPaneReviewComments = new JScrollPane();
		reviewComments = new FadingTextArea();
		separatorReviewProduct = new JSeparator();
		productNameLabel = new JLabel();
		productName = new CompletableJTextField();
		productVersionLabel = new JLabel();
		productVersion = new CompletableJTextField();
		productReferenceLabel = new JLabel();
		radioBtnRefAsText = new FormLabel();
		scrollPaneProductReference = new JScrollPane();
		productReferenceText = new FadingTextArea();
		separatorReferenceTextFile = new JSeparator();
		radioBtnRefAsFile = new FormLabel();
		scrollPaneReferenceFile = new JScrollPane();
		productReferenceModel = new DefaultListModel();
		productReferenceList = new JList(productReferenceModel);
		productReferenceList.getSelectionModel().addListSelectionListener(
				new FileReferenceListSelectionListener());
		productReferenceList.addMouseListener(
				new OpenFileReferenceMouseAdapter());
		addReferenceBtn = new JButton();
		deleteReferenceBtn = new JButton();
		JPanel formPanel = new JPanel();
		  
		this.setLayout(new BorderLayout());
		formPanel.setOpaque(false);
			   
		setBackground(new Color(214, 214, 214));
			   
		//---- separatorReviewProduct ----
		separatorReviewProduct.setBackground(new Color(0x828790));
		separatorReviewProduct.setForeground(new Color(0xd4d4d4));
			   
		//---- separatorReferenceTextFile ----
		separatorReferenceTextFile.setBackground(new Color(0x828790));
		separatorReferenceTextFile.setForeground(new Color(0xd4d4d4));


		//---- reviewNameLabel ----
		reviewNameLabel.setText(Messages.getString(
				"PearReview.Moderator.review.name"));
		reviewNameLabel.setFont(getFont());

		//---- reviewName ----
		reviewName.setFont(getFont());
		reviewName.setBorder(BorderFactory.createMatteBorder(
				1, 1, 1, 1, new Color(0x828790)));

		//---- ReviewDescriptionLabel ----
		ReviewDescriptionLabel.setText(Messages.getString(
				"PearReview.Moderator.review.description"));
		ReviewDescriptionLabel.setFont(getFont());

		//======== scrollPaneReviewDescription ========
		{

				//---- reviewDescription ----
				reviewDescription.setFont(new Font(
				"Tahoma", Font.PLAIN, 12));
				reviewDescription.setLineWrap(true);
				scrollPaneReviewDescription.setViewportView(
				reviewDescription);
		}

		//---- reviewCommentsLabel ----
		reviewCommentsLabel.setText(Messages.getString(
				"PearReview.Moderator.review.comments"));
		reviewCommentsLabel.setFont(getFont());

		//======== scrollPaneReviewComments ========
		{

			//---- reviewComments ----
			reviewComments.setFont(getFont());
			reviewComments.setLineWrap(true);
			scrollPaneReviewComments.setViewportView(
			reviewComments);
		}

		//---- productNameLabel ----
		productNameLabel.setText(Messages.getString(
				"PearReview.Moderator.product.name"));
		productNameLabel.setFont(getFont());

		//---- productName ----
		productName.setFont(new Font("Tahoma", Font.PLAIN, 12));
		productName.setBorder(BorderFactory.createMatteBorder(
				1, 1, 1, 1, new Color(0x828790)));

		//---- productVersionLabel ----
		productVersionLabel.setText(Messages.getString(
				"PearReview.Moderator.product.version"));
		productVersionLabel.setFont(getFont());

		//---- productVersion ----
		productVersion.setFont(new Font("Tahoma", Font.PLAIN, 12));
		productVersion.setBorder(BorderFactory.createMatteBorder(
				1, 1, 1, 1, new Color(0x828790)));

		//---- productReferenceLabel ----
		productReferenceLabel.setText(Messages.getString(
				"PearReview.Moderator.product.referece"));
		productReferenceLabel.setFont(getFont());

		//---- radioBtnRefAsText ----
		radioBtnRefAsText.setText(Messages.getString(
				"PearReview.Moderator.product.referece.text"));

		//======== scrollPaneProductReference ========
		{

			//---- produrctReferenceText ----
			productReferenceText.setFont(getFont());
			productReferenceText.setLineWrap(true);
			scrollPaneProductReference.setViewportView(
			productReferenceText);
		}

		//---- radioBtnRefAsFile ----
		radioBtnRefAsFile.setText(Messages.getString(
				"PearReview.Moderator.product.referece.file"));

		//======== scrollPaneReferenceFile ========
		{

			//---- productReferenceList ----
			productReferenceList.setFont(getFont());
			productReferenceList.setBorder(
			BorderFactory.createEmptyBorder(0,0,0,0));
			productReferenceList.setSelectionBackground(new Color(0xbfd72b));
			scrollPaneReferenceFile.setViewportView(
			productReferenceList);
			scrollPaneReferenceFile.setBorder(
			BorderFactory.createMatteBorder(1, 1, 1, 1, new Color(0x828790)));
			URIListCellRenderer renderer = new URIListCellRenderer();
			productReferenceList.addMouseListener(renderer);
			productReferenceList.addMouseMotionListener(renderer);
			productReferenceList.setCellRenderer(renderer);
			ToolTipManager.sharedInstance()
					.registerComponent(productReferenceList);
		}

		//---- addReferenceBtn ----
		addReferenceBtn.setAction(new AddFileReferenceAction());
		addReferenceBtn.setText(Messages.getString(
				"PearReview.Moderator.add_btn"));
		addReferenceBtn.setFont(getFont());

		//---- deleteReferenceBtn ----
		deleteReferenceBtn.setAction(deleteFileReferenceAction);
		deleteReferenceBtn.setText(Messages.getString(
				"PearReview.Moderator.delete_btn"));
		deleteReferenceBtn.setFont(getFont());
			   
		GroupLayout layout = new GroupLayout(formPanel);
			   
		formPanel.setLayout(layout);
				layout.setHorizontalGroup(
					layout.createParallelGroup()
						.addGroup(layout.createSequentialGroup()
						.addContainerGap()
						.addGroup(layout.createParallelGroup()
						.addGroup(layout.createSequentialGroup()
						.addGroup(layout.createParallelGroup()
								.addComponent(separatorReviewProduct,
										GroupLayout.Alignment.TRAILING,
										GroupLayout.DEFAULT_SIZE,
										657,
										GroupLayout.PREFERRED_SIZE)
								.addGroup(GroupLayout.Alignment.LEADING,
										layout.createSequentialGroup()
								.addGroup(layout.createParallelGroup()
								.addComponent(reviewNameLabel,
										GroupLayout.Alignment.LEADING,
										GroupLayout.DEFAULT_SIZE,
										80,
										GroupLayout.PREFERRED_SIZE)
								.addComponent(ReviewDescriptionLabel,
										GroupLayout.Alignment.LEADING,
										GroupLayout.DEFAULT_SIZE,
										80,
										GroupLayout.PREFERRED_SIZE)
								.addComponent(reviewCommentsLabel,
										GroupLayout.Alignment.LEADING,
										GroupLayout.DEFAULT_SIZE,
										80,
										GroupLayout.PREFERRED_SIZE))
								.addGap(57, 57, 57)
								.addGroup(layout.createParallelGroup(
										GroupLayout.Alignment.TRAILING)
								.addComponent(scrollPaneReviewComments,
										GroupLayout.Alignment.LEADING,
										GroupLayout.DEFAULT_SIZE,
										520,
										GroupLayout.PREFERRED_SIZE)
								.addComponent(scrollPaneReviewDescription,
										GroupLayout.Alignment.LEADING,
										GroupLayout.DEFAULT_SIZE,
										520,
										GroupLayout.PREFERRED_SIZE)
								.addComponent(reviewName,
										GroupLayout.Alignment.LEADING,
										GroupLayout.PREFERRED_SIZE,
										300,
										GroupLayout.PREFERRED_SIZE)))
								.addGroup(layout.createSequentialGroup()
										.addGroup(layout.createParallelGroup()
								.addComponent(productNameLabel,
										GroupLayout.Alignment.LEADING,
										GroupLayout.DEFAULT_SIZE,
										80,
										GroupLayout.PREFERRED_SIZE))
								.addGap(57, 57, 57)
								.addGroup(layout.createParallelGroup()
								.addComponent(productVersion,
										GroupLayout.DEFAULT_SIZE,
										300,
										GroupLayout.PREFERRED_SIZE)
								.addComponent(productName,
										GroupLayout.DEFAULT_SIZE,
										300,
										GroupLayout.PREFERRED_SIZE)
								.addGroup(layout.createSequentialGroup()
								.addGroup(layout.createParallelGroup()
								.addComponent(radioBtnRefAsText)
								.addComponent(scrollPaneProductReference,
										 GroupLayout.DEFAULT_SIZE,
										 300,
										 GroupLayout.PREFERRED_SIZE))
								.addGap(20)
								.addGroup(layout.createParallelGroup()
								.addComponent(radioBtnRefAsFile)
								.addComponent(scrollPaneReferenceFile,
										GroupLayout.DEFAULT_SIZE,
										200,
										GroupLayout.PREFERRED_SIZE)))
								 .addGroup(layout.createSequentialGroup()
								 .addGap(320)
								 .addComponent(addReferenceBtn)
								 .addPreferredGap(LayoutStyle
										 .ComponentPlacement.RELATED,
										 10,
										 GroupLayout.PREFERRED_SIZE)
								 .addComponent(deleteReferenceBtn))))))
								 .addGroup(layout.createSequentialGroup()
								 .addGroup(layout.createParallelGroup()
								 .addComponent(productVersionLabel,
										 GroupLayout.Alignment.LEADING,
										 GroupLayout.DEFAULT_SIZE,
										 80,
										 GroupLayout.PREFERRED_SIZE)
								  .addComponent(productReferenceLabel,
										 GroupLayout.Alignment.LEADING,
										 GroupLayout.DEFAULT_SIZE,
										 80,
										 GroupLayout.PREFERRED_SIZE)))))
				);
				layout.setVerticalGroup(
						layout.createParallelGroup()
								.addGroup(layout.createSequentialGroup()
										.addContainerGap()
										.addGroup(layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
										.addComponent(reviewNameLabel)
										.addComponent(reviewName,
												 GroupLayout.PREFERRED_SIZE,
												 GroupLayout.DEFAULT_SIZE,
												 GroupLayout.PREFERRED_SIZE))
								 .addPreferredGap(LayoutStyle
										 .ComponentPlacement.UNRELATED)
								 .addGroup(layout.createParallelGroup()
										 .addComponent(ReviewDescriptionLabel)
										 .addComponent(
												 scrollPaneReviewDescription,
												 GroupLayout.PREFERRED_SIZE,
												 70,
												 GroupLayout.PREFERRED_SIZE))
								 .addGap(15, 15, 15)
								 .addGroup(layout.createParallelGroup()
										 .addComponent(reviewCommentsLabel)
										 .addComponent(
												 scrollPaneReviewComments,
												 GroupLayout.PREFERRED_SIZE,
												 70,
												 GroupLayout.PREFERRED_SIZE))
										.addGap(18, 18, 18)
										.addComponent(separatorReviewProduct,
												 GroupLayout.PREFERRED_SIZE,
												 GroupLayout.DEFAULT_SIZE,
												 GroupLayout.PREFERRED_SIZE)
										.addGap(18)
										.addGroup(layout.createParallelGroup(
												GroupLayout.Alignment.BASELINE)
										.addComponent(productNameLabel)
										.addComponent(productName,
												GroupLayout.PREFERRED_SIZE,
												GroupLayout.DEFAULT_SIZE,
												GroupLayout.PREFERRED_SIZE))
										.addPreferredGap(LayoutStyle
												.ComponentPlacement.UNRELATED)
										.addGroup(layout.createParallelGroup(
														GroupLayout.Alignment
														.BASELINE)
												.addComponent(
														productVersionLabel)
										.addComponent(productVersion,
												 GroupLayout.PREFERRED_SIZE,
												 GroupLayout.DEFAULT_SIZE,
												 GroupLayout.PREFERRED_SIZE))
										.addPreferredGap(LayoutStyle
												.ComponentPlacement.UNRELATED)
										.addGroup(layout.createParallelGroup()
												.addComponent(
														productReferenceLabel)
												.addComponent(
														radioBtnRefAsText)
												.addComponent(
														radioBtnRefAsFile)
												
										)
										.addPreferredGap(LayoutStyle
												.ComponentPlacement.UNRELATED)
										.addGroup(layout.createParallelGroup()
												.addGroup(layout
														.createParallelGroup()
										.addComponent(
												scrollPaneProductReference,
												GroupLayout.PREFERRED_SIZE,
												70,
												GroupLayout.PREFERRED_SIZE))
										.addGap(14, 14, 14)
									 
										.addGroup(layout.createParallelGroup()
										.addComponent(scrollPaneReferenceFile,
												GroupLayout.PREFERRED_SIZE,
												70,
												GroupLayout.PREFERRED_SIZE))
										 )
										.addPreferredGap(LayoutStyle
												.ComponentPlacement.RELATED)
										.addGroup(layout.createParallelGroup()
												.addComponent(addReferenceBtn)
												.addComponent(
														deleteReferenceBtn))
										.addContainerGap(
												GroupLayout.DEFAULT_SIZE,
														Short.MAX_VALUE))
				);
		
		formPanel.setPreferredSize(new Dimension(300, 300));
		add(formPanel, BorderLayout.CENTER);
		add(new HeadingLabel(Messages.getString(
						"PearReview.Moderator.tabs.information")), 
						BorderLayout.NORTH);
		bottom = new BottomButtonPanel();
		add(bottom, BorderLayout.SOUTH);
	}
	   
	private class AddFileReferenceAction extends AbstractAction {
		private static final long serialVersionUID = -617123119049467560L;
		@Override
		public void actionPerformed(ActionEvent e) {
			JFileChooser openDialog = new JFileChooser();
			openDialog.setMultiSelectionEnabled(true);
			openDialog.setCurrentDirectory(lastDir);
			
			if (JFileChooser.APPROVE_OPTION == 
					openDialog.showOpenDialog(InformationPanel.this)) {
				
				File[] files = openDialog.getSelectedFiles();
				URI[] uris = new URI[files.length];
				for(int i = 0; i < files.length ; i++) {
					File f = files[i];
					URI uri = f.toURI();
					uris[i] = uri;
							   
					if (!productReferenceModel.contains(uri)) {
						productReferenceModel.addElement(uri);
						lastDir = f;
					}
					
					productReferenceList.setSelectedValue(uri, true);
				}
				
				/* select uri's */
				productReferenceList.clearSelection();
				for(int i = 0; i < files.length ; i++) {
					int index = productReferenceModel.indexOf(uris[i]);
					productReferenceList.addSelectionInterval(index, index);
				}
				
			}
				   
		}
	}
	   
	private class DeleteFileReferenceAction extends AbstractAction {
		private static final long serialVersionUID = 1999290830576127170L;
		public DeleteFileReferenceAction() {
			setEnabled(false);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			Object[] uris = productReferenceList.getSelectedValues();
			for(Object uri: uris) {
				productReferenceModel.removeElement(uri);
			}
		}
	}
	
	private class FileReferenceListSelectionListener 
			implements ListSelectionListener, Serializable {
		private static final long serialVersionUID = 3986430456886998793L;
		@Override
		public void valueChanged(ListSelectionEvent e) {
			deleteFileReferenceAction.setEnabled(
					!productReferenceList.isSelectionEmpty());
		}
	}
	
	private class OpenFileReferenceMouseAdapter extends DoubleClickMouseAdapter{
		private static final long serialVersionUID = 1997399054977309975L;
		@Override
		public void mouseDoubleClicked(MouseEvent me) {
			try {
				Object value = productReferenceList.getSelectedValue();
				URI uriToOpen = null;
				
				if(value instanceof URI) {
					uriToOpen = (URI) value;
				} else if(value instanceof File) {
					uriToOpen = ((File) value).toURI();
				}
				
				if(uriToOpen != null) {
					Desktop.getDesktop().browse(uriToOpen);
				}
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public String getHint() {
		return Messages.getString("PearReview.hint.moderator.information");
	}
	
	@Override
	public String getErrorMessage() {
		return null;
	}
	
	@Override
	public void setNextViewAction(Action action) {
		bottom.setNextViewAction(action);
	}

	@Override
	public void setPreviousViewAction(Action action) {
		bottom.setPreviousViewAction(action);
	}
}

